#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include <stdlib.h>
#include "hi_gpio.h"
#include "hi_io.h"
#include "hi_adc.h"
#include "hi_errno.h"
#include "math.h"
#include <errno.h>
// #include "wifi_connecter.h"
// #include "net_common.h"

#include "init.h"
#include "ssd1306/ssd1306.h"
#include "ssd1306/ssd1306_sdk.h"
#define SCOUNT 30              // TDS采样次数
#define host "175.178.100.193" // your PC IP address
#define stepPin 7              // 控制引脚
#define dirPin 8               // 方向引脚
#define MAX_TIMEOUTS 3         // udp发送请求最大超时重发次数
#define OLED_I2C_BAUDRATE 400 * 1000

int state = 1;                // 水阀状态，0：关，1：开；
int water_id = 001;           // 水表ID
static char request[25] = ""; // 发送的消息
static char request1[2] = ""; // 发送的消息

static char response[128] = "";
static char response1[128] = "";
const int stepsPerRevolution = 51; // 电机转90°
int num = 0;                       // 水流量脉冲数
float analogBuffer[SCOUNT];        // 将从ADC读取的模拟值存储在数组中
int analogBuffer1[SCOUNT];         // 将从ADC读取的模拟值存储在数组中
float analogBufferTemp[SCOUNT];    // 盗版上一个数组
float analogBufferTemp1[SCOUNT];   // 盗版上一个数组
int analogBufferIndex = 0, analogBufferIndex1 = 0, copyIndex = 0, copyIndex1 = 0;
float averageVoltage = 0, tdsValue = 0, temperature0 = 25, temperature = 0; // 常温，待测温度
float p = 600.0;                                                            // 为1L水所需要的脉冲
float f;                                                                    // 实际水流量
float v;                                                                    // 流速
float Hydraulic;                                                            // 压力
int timeouts = 0;                                                           // 超时重发次数
int flage = 0;                                                              // 开始采样标记，1开始采样
int flage1 = 0;                                                             // 开始上传数据标志
float history_f;                                                            // 历史水流量

double MYLOG(double a) // 数学中的ln函数
{
    int N = 15; // 我们取了前15+1项来估算
    int k, nk;
    double x, xx, y;
    x = (a - 1) / (a + 1);
    xx = x * x;
    nk = 2 * N + 1;
    y = 1.0 / nk;
    for (k = N; k > 0; k--)
    {
        nk = nk - 2;
        y = 1.0 / nk + xx * y;
    }
    return 2.0 * x * y;
}

void Func() // 中断回调函数测水流量
{
    num++;
}

float getMedianNum(float bArray[], int iFilterLen) // 均值滤波算法
{
    float bTab[iFilterLen];
    for (int i = 0; i < iFilterLen; i++)
        bTab[i] = bArray[i];
    int i, j;
    float bTemp;
    for (j = 0; j < iFilterLen - 1; j++)
    {
        for (i = 0; i < iFilterLen - j - 1; i++)
        {
            if (bTab[i] > bTab[i + 1])
            {
                bTemp = bTab[i];
                bTab[i] = bTab[i + 1];
                bTab[i + 1] = bTemp;
            }
        }
    }
    if ((iFilterLen & 1) > 0)
    {
        bTemp = bTab[(iFilterLen - 1) / 2];
    }
    else
    {
        bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
    }

    return bTemp;
}

void Turn_Off()
{
    if (state == 1)
    {
        printf("now is turn off!\n");
        hi_gpio_set_ouput_val(dirPin, 1);
        for (int x = 0; x < stepsPerRevolution; x++)
        {
            hi_gpio_set_ouput_val(stepPin, 1);
            usleep(2000);
            hi_gpio_set_ouput_val(stepPin, 0);
            usleep(2000);
            // printf("now is step 1\n");
        }
        state = 0;
        printf("turn off down   state: %d\n", state);
    }

    // printf("Turn off down-_-\n");
}

void Turn_On()
{
    if (state == 0)
    {
        printf("now is turn on!\n");
        hi_gpio_set_ouput_val(dirPin, 0);
        for (int x = 0; x < stepsPerRevolution; x++)
        {
            hi_gpio_set_ouput_val(stepPin, 1);
            usleep(2000);
            hi_gpio_set_ouput_val(stepPin, 0);
            usleep(2000);
            // printf("now is step 1\n");
        }
        state = 1;
        printf("turn on down    state: %d\n", state);
    }
    // printf("Turn on down-_-\n");
}

static void AdcGpioTask(void *arg)
{
    (void)arg;

    hi_u16 value;                      // 存温度的
    hi_u16 value1;                     // 存TDS的
    hi_u16 value2;                     // 存水压的
    const float thermistorR = 50000.0; // 温度传感器的分压电阻
    const float T0 = 298.15;           // 热敏电阻在25摄氏度下的温度，单位为开尔文
    const float B = 3950.0;            // 热敏电阻的B值
    float Vntc, Rntc;                  // 热敏电阻的电压、电阻
    float Vtemp;
    int average = 0, sum = 0;
    float date[5];         // 存储数据
    char strArray[20][33]; // 存储转换后的字符串数组包括终止符'\0'

    while (1)
    {
        // 1.测水流量
        printf("-----------start---------\n");
        hi_gpio_register_isr_function(HI_GPIO_IDX_4, HI_INT_TYPE_EDGE, HI_GPIO_EDGE_RISE_LEVEL_HIGH, Func, NULL); // 上升沿中断
        f = (float)num / p;                                                                                       // 用了多少升水
        printf("num:%d\n", num);
        printf("water : %fL\n", f + history_f); // 打印水流量
        Water_Ssd1306_Update(water_screen_water, f + history_f);
        date[0] = f + history_f;
        usleep(100000);
        // 2.测温度
        if (hi_adc_read(HI_ADC_CHANNEL_0, &value, HI_ADC_EQU_MODEL_8, HI_ADC_CUR_BAIS_DEFAULT, 0) != HI_ERR_SUCCESS) // 读取引脚的模拟信号
        {
            printf("ADC read error!\n");
        }
        else
        {
            Vntc = ((float)value * 4 * 1.8) / 4096.0; // 将模拟量转换成实际电压值
            // Vntc = Vntc + 1;
            Vtemp = Vntc + 0.1;
            Rntc = (thermistorR * Vtemp) / (5.0 - Vtemp); // 分压公式
            printf("V = %f\n", Vntc);
            printf("Vtemp = %f\n", Vtemp);
            printf("R = %f\n", Rntc / 1000);
            temperature = (1 / (MYLOG((double)Rntc / (double)thermistorR) / B + (1 / T0))) - 273.15; // 热敏电阻计算温度的固定公式
            Water_Ssd1306_Update(water_screen_temp, temperature);
            printf("temp = %.2f\n", temperature);
            if (temperature >= 40)
            {
                hi_gpio_set_ouput_val(HI_GPIO_IDX_2, 1);
            }
            else
            {
                hi_gpio_set_ouput_val(HI_GPIO_IDX_2, 0);
            }
            date[1] = temperature;
            usleep(100000);
        }

        // 3.测TDS
        if (hi_adc_read(HI_ADC_CHANNEL_4, &value1, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0) != HI_ERR_SUCCESS)
        {
            printf("TDS read error!\n");
        }
        else
        {
            // printf("value1:%d\n", value1);
            analogBuffer[analogBufferIndex] = (value1 * 4 * 1.8) / 4096; // 转换成电压
            // averageVoltage = ((float)value1 * 4 * 1.8) / 4096.0;
            // printf("analogBuffer[%d]:%f\n", analogBufferIndex, analogBuffer[analogBufferIndex]);
            analogBufferIndex++;
            if (analogBufferIndex == SCOUNT)
            {
                analogBufferIndex = 0;
            }
            for (copyIndex = 0; copyIndex < SCOUNT; copyIndex++)
            {
                analogBufferTemp[copyIndex] = analogBuffer[copyIndex];
            }
            averageVoltage = getMedianNum(analogBufferTemp, SCOUNT); // 通过中值滤波算法读取更稳定的模拟值，并转换为电压值
            // printf("TDS_averageV1:%.2f\n", ((float)value1 * 4 * 1.8) / 4096.0);
            // averageVoltage = ((float)value1 * 4 * 1.8) / 4096.0;
            printf("TDS_averageV2:%f\n", averageVoltage);
            tdsValue = (133.42 * averageVoltage * averageVoltage * averageVoltage - 255.86 * averageVoltage * averageVoltage + 857.39 * averageVoltage) * 1.18;
            // ECvalue25  =  ecvalue / (1.0+0.02*(temperature-25.0));
            tdsValue = tdsValue / (1.0 + 0.02 * (22 - 25.0));
            tdsValue = tdsValue / 2;
            Water_Ssd1306_Update(water_screen_TDS, tdsValue);
            printf("TDS:%.2fppm\n", tdsValue);
            date[2] = tdsValue;
            usleep(100000);
        }

        // 4.测水压
        if (hi_adc_read(HI_ADC_CHANNEL_2, &value2, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0) != HI_ERR_SUCCESS)
        {
            printf("Hydraulic read error!\n");
        }
        else
        {
            Hydraulic = (value2 * 4 * 1.8) / 4096; // 转换成电压
            // printf("value2:%f", Hydraulic);
            Water_Ssd1306_Update(water_screen_Hydraulic, (200 * Hydraulic));
            printf("Hydraulic:%.2fKpa\n", (200 * Hydraulic));
            date[3] = 200 * Hydraulic;
            usleep(100000);
        }

        for (int i = 0; i < 4; i++)
        {
            sprintf(strArray[i], "%f", date[i]);
        }

        printf("-----------end---------\n");
        usleep(1000000);
        Turn_Off();
        usleep(4000000);
        Turn_On();
    }
}

static void AdcGpioEntry(void)
{
    printf("ADC Test!\n");
    osThreadAttr_t attr;
    Water_GPIO_Init();
    Water_Ssd1306_Init();

    attr.name = "AdcGpioTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 30720;
    attr.priority = 25;

    if (osThreadNew(AdcGpioTask, NULL, &attr) == NULL)
    {
        printf("[LedExample] Falied to create LedTask!\n");
    }
}

SYS_RUN(AdcGpioEntry);